#ifndef CLEFTVIEW_HPP
#define CLEFTVIEW_HPP

#include <math.h>
#include <time.h>
#include <shlobj.h>
#include <shtypes.h>
#include <windows.h>
#include <strsafe.h>
#include <commctrl.h>

class CLeftView
{
public:
    CLeftView() {}
    ~CLeftView() {}
    CLeftView(LPCTSTR lpszClassName, HINSTANCE hInstance)
    {
        m_hWnd = NULL;
        m_hParent = NULL;
        m_wcex = {0};
        m_hFont = NULL;
        m_rcMenuBar = {0};
        m_rcToolBar = {0};
        m_scanColor = RGB(0, 255, 0);
        m_scanBkColor = RGB(0, 200, 0);
        m_rcStatus = {0};
        m_rcCurTime = {0};
        m_rcReqNums = {0};
        m_rcRspNums = {0};
        Register(lpszClassName, hInstance);
    }
    CLeftView(const CLeftView &) = delete;
    CLeftView &operator=(const CLeftView &) = delete;
    HWND GetHWND() const
    {
        return m_hWnd;
    }
    void SetToolBarRect(RECT rcToolBar)
    {
        m_rcToolBar = rcToolBar;
    }
    void SetMenuBarRect(RECT rcMenuBar)
    {
        m_rcMenuBar = rcMenuBar;
    }
    void SetScanBkColor(COLORREF scanBkColor)
    {
        m_scanBkColor = scanBkColor;
    }
    HFONT GetFont(TCHAR *lpFont, UINT uSize = 20)
    {
        if (m_hFont)
        {
            return m_hFont;
        }
        else
        {
            LOGFONT logfont;
            ZeroMemory(&logfont, sizeof(LOGFONT));
            logfont.lfHeight = uSize;
            if (lpFont)
            {
                StringCchCopy(logfont.lfFaceName, 255, lpFont);
            }
            else
            {
                StringCchCopy(logfont.lfFaceName, 255, TEXT("Microsoft YaHei"));
            }
            m_hFont = CreateFontIndirect(&logfont);
            return m_hFont;
        }
    }
    LRESULT Register(LPCTSTR lpszClassName, HINSTANCE hInstance)
    {
        m_wcex = {0};
        m_wcex.cbSize = sizeof(WNDCLASSEX);
        m_wcex.cbClsExtra = 0;                                                                     // 类的额外内存
        m_wcex.cbWndExtra = 0;                                                                     // 窗口额外内存
        m_wcex.hbrBackground = GetSysColorBrush(/*COLOR_3DFACE*/ COLOR_3DSHADOW /*COLOR_3DSHADOW*/); // 背景
        m_wcex.hCursor = LoadCursor(NULL, IDC_ARROW);                                              // 光标 第一个为NULL代表使用系统提供的光标
        m_wcex.hIcon = LoadIcon(NULL, IDI_APPLICATION);                                            // 图标 第一个为NULL代表使用系统提供的图标
        m_wcex.hInstance = hInstance;                                                              // 应用程序实例句柄
        m_wcex.lpfnWndProc = CLeftView::WndProc;                                                   // 回调函数
        m_wcex.lpszClassName = lpszClassName;                                                      // 窗口类名称
        m_wcex.lpszMenuName = NULL;                                                                // 菜单名称
        m_wcex.style = CS_HREDRAW | CS_VREDRAW;                                                    // 显示风格
        m_hInstance = hInstance;
        if (!RegisterClassEx(&m_wcex))
        {
            MessageBox(NULL, TEXT("Failed to register child window class"), TEXT("Error"), MB_OK | MB_ICONERROR);
            return -1;
        }
        return 0;
    }
    LRESULT Create(HWND hParent, LPRECT lpRect, LPCTSTR szWindowName)
    {
        // Create the child window
        RECT rect;
        if (!lpRect)
        {
            GetClientRect(hParent, &rect);
            lpRect = &rect;
        }
        m_nMenuBarHeight = m_rcMenuBar.bottom - m_rcMenuBar.top;
        m_nToolBarHeight = m_rcToolBar.bottom - m_rcToolBar.top;
        lpRect->top += m_nToolBarHeight;
        m_hWnd = CreateWindow(m_wcex.lpszClassName, szWindowName, WS_CHILD | WS_VISIBLE,
                              lpRect->left, lpRect->top, lpRect->right - lpRect->left, lpRect->bottom - lpRect->top,
                              hParent, NULL, m_hInstance, this);
        m_hParent = hParent;
        SetWindowLongPtr(m_hWnd, GWLP_USERDATA, (LONG_PTR)this);

        CreateLeftCtrl();
        return 0;
    }
    void CreateLeftCtrl()
    {
        RECT rect;
        GetClientRect(m_hParent, &rect);
        rect.left = rect.left + nWindowEdge;
        rect.top = rect.top + nWindowEdge;
        rect.right = rect.right - rect.left - nWindowEdge;
        rect.bottom = rect.bottom - rect.top - m_nToolBarHeight - nWindowEdge;
        m_hGroupBoxText = CreateWindow(TEXT("Button"), TEXT("系统信息"), WS_CHILD | WS_VISIBLE | BS_GROUPBOX, rect.left, rect.top, rect.right, rect.bottom, m_hWnd, (HMENU)0, NULL, NULL);
        m_hRunStatusText = CreateWindow(TEXT("Static"), TEXT("运行状态："), WS_CHILD | WS_VISIBLE, nTextCtrlLeft, nLineHeight, nTextCtrlWidth, nTextCtrlHeight, m_hWnd, (HMENU)1, NULL, NULL);
        m_hCurTimeText = CreateWindow(TEXT("Static"), TEXT("当前时间："), WS_CHILD | WS_VISIBLE, nTextCtrlLeft, nLineHeight * 2, nTextCtrlWidth, nTextCtrlHeight, m_hWnd, (HMENU)2, NULL, NULL);
        m_hTodayReqText = CreateWindow(TEXT("Static"), TEXT("当日请求："), WS_CHILD | WS_VISIBLE, nTextCtrlLeft, nLineHeight * 3, nTextCtrlWidth, nTextCtrlHeight, m_hWnd, (HMENU)3, NULL, NULL);
        m_hTodayRspText = CreateWindow(TEXT("Static"), TEXT("当日响应："), WS_CHILD | WS_VISIBLE, nTextCtrlLeft, nLineHeight * 4, nTextCtrlWidth, nTextCtrlHeight, m_hWnd, (HMENU)4, NULL, NULL);
        SendMessage(m_hGroupBoxText, WM_SETFONT, (WPARAM)GetFont(NULL), TRUE);
        SendMessage(m_hRunStatusText, WM_SETFONT, (WPARAM)GetFont(NULL), TRUE);
        SendMessage(m_hCurTimeText, WM_SETFONT, (WPARAM)GetFont(NULL), TRUE);
        SendMessage(m_hTodayReqText, WM_SETFONT, (WPARAM)GetFont(NULL), TRUE);
        SendMessage(m_hTodayRspText, WM_SETFONT, (WPARAM)GetFont(NULL), TRUE);

        // 运行状态图形标识
        GetClientRect(m_hRunStatusText, &m_rcStatus);
        m_rcStatus.left = nTextCtrlLeft + nTextCtrlWidth + nColWidth;
        m_rcStatus.top = nLineHeight;
        m_rcStatus.right = m_rcStatus.left + nTextCtrlHeight;
        m_rcStatus.bottom = m_rcStatus.top + nTextCtrlHeight;

        GetClientRect(m_hCurTimeText, &m_rcCurTime);
        m_rcCurTime.left = nTextCtrlLeft + nTextCtrlWidth + nColWidth;
        m_rcCurTime.top = nLineHeight * 2;
        m_rcCurTime.right = m_rcCurTime.left + nTextCtrlWidth * 2;
        m_rcCurTime.bottom = m_rcCurTime.top + nTextCtrlHeight;

        GetClientRect(m_hTodayReqText, &m_rcReqNums);
        m_rcReqNums.left = nTextCtrlLeft + nTextCtrlWidth + nColWidth;
        m_rcReqNums.top = nLineHeight * 3;
        m_rcReqNums.right = m_rcReqNums.left + nTextCtrlWidth;
        m_rcReqNums.bottom = m_rcReqNums.top + nTextCtrlHeight;

        GetClientRect(m_hTodayRspText, &m_rcRspNums);
        m_rcRspNums.left = nTextCtrlLeft + nTextCtrlWidth + nColWidth;
        m_rcRspNums.top = nLineHeight * 4;
        m_rcRspNums.right = m_rcRspNums.left + nTextCtrlWidth;
        m_rcRspNums.bottom = m_rcRspNums.top + nTextCtrlHeight;

        // CreateWindow(TEXT("Static"), TEXT("lyrics"), WS_CHILD | WS_VISIBLE | SS_LEFT, 140, 20, 50, 100, m_hWnd, (HMENU)1, NULL, NULL);
        // HBITMAP hBitmap = (HBITMAP)LoadImage(NULL, TEXT("./bitmap/test19_cartesian_canvas02.bmp"), IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
        // HWND hsti = CreateWindow(TEXT("Static"), TEXT(""), WS_CHILD | WS_VISIBLE | SS_BITMAP, 220, 20, 0, 0, m_hWnd, (HMENU)1, NULL, NULL);
        // SendMessage(hsti, STM_SETIMAGE, (WPARAM)IMAGE_BITMAP, (LPARAM)hBitmap);
    }
    static LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
    {
        if (uMsg == WM_CREATE)
        {
            SetTimer(hWnd, 1, 10, NULL);
        }
        CLeftView *pThis = (CLeftView *)GetWindowLongPtr(hWnd, GWLP_USERDATA);
        if (pThis)
        {
            return pThis->WindowProc(hWnd, uMsg, wParam, lParam);
        }
        return DefWindowProc(hWnd, uMsg, wParam, lParam);
    }
    LRESULT CALLBACK WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
    {
        switch (uMsg)
        {
        case WM_TIMER:
        {
            if (wParam == 1)
            {
                RECT rect;
                rect.left = m_rcStatus.left - 10;
                rect.top = m_rcStatus.top - 10;
                rect.right = m_rcStatus.right + 10;
                rect.bottom = m_rcStatus.bottom + 10;
                InvalidateRect(hWnd, &rect, TRUE);
                InvalidateRect(hWnd, &m_rcCurTime, TRUE);
                InvalidateRect(hWnd, &m_rcReqNums, TRUE);
                InvalidateRect(hWnd, &m_rcRspNums, TRUE);
            }
            break;
        }
        case WM_PAINT:
        {
            PAINTSTRUCT ps;
            HDC hdc = BeginPaint(hWnd, &ps);
            HPEN hPen = CreatePen(PS_NULL, 1, m_scanBkColor);
            HPEN holdPen = (HPEN)SelectObject(hdc, hPen);
            HBRUSH hBrush = CreateSolidBrush(/*m_scanBkColor*/ m_scanBkColor /*RGB(0, 255, 200)*/);
            HBRUSH holdBrush = (HBRUSH)SelectObject(hdc, hBrush);

            // FillRect(hdc, &m_rcStatus, hBrush);
            // FillRect(hdc, &m_rcCurTime, hBrush);
            // FillRect(hdc, &m_rcReqNums, hBrush);
            // FillRect(hdc, &m_rcRspNums, hBrush);
            Ellipse(hdc, m_rcStatus.left, m_rcStatus.top, m_rcStatus.right, m_rcStatus.bottom);
            DrawClock(hdc, &m_rcStatus);
            DrawCurTime(hdc, &m_rcCurTime);
            DrawReqNums(hdc, &m_rcReqNums);
            DrawRspNums(hdc, &m_rcRspNums);

            SelectObject(hdc, holdPen);
            SelectObject(hdc, holdBrush);
            DeleteObject(hPen);
            DeleteObject(hBrush);
            ReleaseDC(hWnd, hdc);
            EndPaint(hWnd, &ps);
            break;
        }
        case WM_CTLCOLORSTATIC:
        {
            HDC hdc = (HDC)wParam;
            SetTextColor(hdc, COLOR_3DFACE);
            return (LRESULT)GetStockObject(COLOR_3DFACE);
        }
        case WM_COMMAND:
        {
            TCHAR szTitle[MAX_PATH] = {0};
            StringCchPrintf(szTitle, 256, TEXT("我收到了: %d"), LOWORD(wParam));
            // MessageBox(0, szTitle, TEXT("我收到了"), MB_OK);
            break;
        }
        case WM_SIZE:
        {
            RECT rcParent;
            GetClientRect(m_hParent, &rcParent);
            rcParent.top += m_rcToolBar.bottom - m_rcToolBar.top;
            MoveWindow(m_hWnd, rcParent.left, rcParent.top, rcParent.right, rcParent.bottom, TRUE);

            RECT rect;
            GetClientRect(m_hParent, &rect);
            rect.left = rect.left + nWindowEdge;
            rect.top = rect.top + nWindowEdge;
            rect.right = rect.right - rect.left - nWindowEdge;
            rect.bottom = rect.bottom - rect.top - m_nToolBarHeight - nWindowEdge;
            MoveWindow(m_hGroupBoxText, rect.left, rect.top, rect.right, rect.bottom, TRUE);

            InvalidateRect(hWnd, NULL, FALSE);
            break;
        }
        case WM_MOUSEMOVE:
        {
            int xPos = LOWORD(lParam);
            int yPos = HIWORD(lParam);
            TCHAR buffer[256];
            StringCchPrintf(buffer, 256, TEXT("xPos: %d, yPos: %d"), xPos, yPos);
            // SetWindowText(m_hParent, buffer);
            break;
        }
        case WM_CLOSE:
        {
            DestroyWindow(hWnd);
            break;
        }
        case WM_DESTROY:
        {
            PostQuitMessage(0);
            break;
        }
        default:
            break;
        }
        return DefWindowProc(m_hWnd, uMsg, wParam, lParam);
    }
    void DrawClock(HDC hdc, LPRECT lpRect)
    {
        static const double pi = 3.1415926535;
        //得到表盘中央位置，即圆心
        int x0 = lpRect->left + (lpRect->right - lpRect->left) / 2;
        int y0 = lpRect->top + (lpRect->bottom - lpRect->top) / 2;
        //得到半径
        int r = (x0 > y0 ? y0 : x0);
        r = r - 5;
        // nums是一圈的点数,Hour为12,Minute和Second为60,Milliseconds为1000
        int nums = 1000;
        //将要在循环中重复的计算提取出来，减少时间复杂度
        double rate = (2.0 * pi / nums);
        double halfPi = pi / 2;
        int zoomR = r - 20;

        // Get Time
        SYSTEMTIME st;
        GetLocalTime(&st);

        HPEN hPen = CreatePen(PS_SOLID, 2, m_scanColor);
        HPEN holdPen = (HPEN)SelectObject(hdc, hPen);
        // 绘制
        MoveToEx(hdc, x0, y0, NULL);
        int secondX = ((zoomR - 25) * sin(rate * st.wMilliseconds) + x0);
        int secondY = (-(zoomR - 25) * sin(rate * st.wMilliseconds + halfPi) + y0);
        LineTo(hdc, secondX, secondY);
        // 还回去
        SelectObject(hdc, holdPen);
        DeleteObject(hPen);
    }
    void DrawCurTime(HDC hdc, LPRECT lpRect)
    {
        // Get Time
        SYSTEMTIME st;
        GetLocalTime(&st);
        size_t lpszLength;
        TCHAR szTimeBuffer[255];
        StringCchPrintf(szTimeBuffer, 255, TEXT("%04d-%02d-%02d %02d:%02d:%02d"), st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond);
        StringCchLength(szTimeBuffer, STRSAFE_MAX_CCH, &lpszLength);
        SelectObject(hdc, GetFont(NULL));
        TextOut(hdc, lpRect->left, lpRect->top, szTimeBuffer, lpszLength);
    }
    void SetReqNums(UINT lpszReqNums)
    {
        m_lpszReqNums = lpszReqNums;
    }
    void SetRspNums(UINT lpszRspNums)
    {
        m_lpszRspNums = lpszRspNums;
    }
    void DrawReqNums(HDC hdc, LPRECT lpRect)
    {
        size_t lpszLength;
        TCHAR szReqBuffer[255];
        StringCchPrintf(szReqBuffer, 255, TEXT("%d"), m_lpszReqNums);
        StringCchLength(szReqBuffer, STRSAFE_MAX_CCH, &lpszLength);
        TextOut(hdc, lpRect->left, lpRect->top, szReqBuffer, lpszLength);
    }
    void DrawRspNums(HDC hdc, LPRECT lpRect)
    {
        size_t lpszLength;
        TCHAR szRspBuffer[255];
        StringCchPrintf(szRspBuffer, 255, TEXT("%d"), m_lpszRspNums);
        StringCchLength(szRspBuffer, STRSAFE_MAX_CCH, &lpszLength);
        TextOut(hdc, lpRect->left, lpRect->top, szRspBuffer, lpszLength);
    }

public:
    UINT nLineHeight = 30;
    UINT nColWidth = 10;
    UINT nTextCtrlLeft = 10;
    UINT nTextCtrlWidth = 80;
    UINT nTextCtrlHeight = 20;
    UINT nWindowEdge = 5;

    HWND m_hGroupBoxText;
    HWND m_hRunStatusText;
    HWND m_hCurTimeText;
    HWND m_hTodayReqText;
    HWND m_hTodayRspText;
    HWND m_hRunStatusVar;
    HWND m_hCurTimeVar;
    HWND m_hTodayReqVar;
    HWND m_hTodayRspVar;
    RECT m_rcStatus;
    RECT m_rcCurTime;
    RECT m_rcReqNums;
    RECT m_rcRspNums;
    UINT m_lpszReqNums = 0;
    UINT m_lpszRspNums = 0;

    UINT m_nMenuBarHeight;
    UINT m_nToolBarHeight;
    COLORREF m_scanColor;
    COLORREF m_scanBkColor;
    HWND m_hWnd;
    HWND m_hParent;
    HFONT m_hFont;
    WNDCLASSEX m_wcex;
    RECT m_rcMenuBar;
    RECT m_rcToolBar;
    HINSTANCE m_hInstance;
};

#endif